#pragma once

#include "Thread.hpp"
#include "Task.hpp"
#include <iostream>
#include <vector>
#include <string>
#include <queue>
#include <functional>
#include <pthread.h>

using namespace MyThread;

const int gthreadnum = 5;
template <typename T>
class ThreadPool
{
private:
    void LockQueue()
    {
        pthread_mutex_lock(&_mutex);
    }
    void UnlockQueue()
    {
        pthread_mutex_unlock(&_mutex);
    }
    void WakeUp()
    {
        pthread_cond_signal(&_cond);
    }
    void WakeupAll()
    {
        pthread_cond_broadcast(&_cond);
    }
    bool IsEmpty()
    {
        return _task_queue.empty();
    }
    void Sleep()
    {
        pthread_cond_wait(&_cond, &_mutex);
    }
    static void test()
    {
        while (1)
        {
            sleep(1);
            std::cout << "我是一个测试任务" << std::endl;
        }
    }
    void HandlerTask(const std::string &name)
    {
        while (1)
        {
            LockQueue();
            // 若任务队列为空&&线程池是运行状态，线程就去休眠
            while (IsEmpty() && _isrunning)
            {
                _sleep_thread++;
                Sleep();
                _sleep_thread--;
            }
            // 如果任务队列是空的&&线程池不是运行状态，就直接退出
            if (IsEmpty() && !_isrunning)
            {
                std::cout << name << " quit" << std::endl;
                UnlockQueue();
                break;
            }

            T t = _task_queue.front();
            _task_queue.pop();
            UnlockQueue();

            // 处理任务
            t();
            std::cout << name << ": " << t.result() << std::endl;
        }
    }

public:
    ThreadPool(const int thread_num = gthreadnum)
        : _thread_num(thread_num), _isrunning(false), _sleep_thread(0)
    {
        pthread_mutex_init(&_mutex, nullptr);
        pthread_cond_init(&_cond, nullptr);
    }

    void Init()
    {
        func_t func = std::bind(&ThreadPool::HandlerTask, this, std::placeholders::_1);
        for (int i = 0; i < _thread_num; i++)
        {
            std::string name = "thread-" + std::to_string(i + 1);
            _threads.emplace_back(name, func);
        }
    }
    void Start()
    {
        _isrunning = true;

        for (auto &thread : _threads)
        {
            thread.Start();
        }
    }
    void Stop()
    {
        LockQueue();
        _isrunning = false;
        // 为了避免退出时还有线程在休眠，要唤醒所有线程
        WakeupAll();
        UnlockQueue();
    }
    void Equeue(const T &in)
    {
        LockQueue();
        // 只有线程池在运行状态时，才不断推送任务
        if (_isrunning)
        {
            _task_queue.push(in);
            if (_sleep_thread > 0) // 有休眠的线程，任务来了，就唤醒
                WakeUp();
        }

        UnlockQueue();
    }
    ~ThreadPool()
    {
        pthread_mutex_destroy(&_mutex);
        pthread_cond_destroy(&_cond);
    }

private:
    int _thread_num;              // 线程个数
    std::vector<Thread> _threads; // 管理线程
    std::queue<T> _task_queue;    // 任务队列
    bool _isrunning; // 线程池的状态

    int _sleep_thread;

    pthread_mutex_t _mutex; // 任务队列时临界资源
    pthread_cond_t _cond;
};
